home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / knowhow4 / choicebx.cpp < prev    next >
C/C++ Source or Header  |  1994-10-10  |  9KB  |  353 lines

  1. #include "choicebx.h"
  2. #include "formline.h"
  3.  
  4. #include <dos.h>
  5.  
  6. #define MAX_STRING 3000
  7.  
  8. ChoiceBox::ChoiceBox(rect coordinates, char* fName, char* h,
  9.            char* HOT, int POS, int START,
  10.            loc ITEMSIZE, char** ITEMSTRINGS,
  11.            int* ITEMLIST,
  12.            loc ITEMDISTANCE,
  13.            rect STATUSPOS,
  14.            int STATUSTYPE, char** STATUSSTRINGS,
  15.            int* STATUSLIST,
  16.            int res, int s, BORDERS b_type, BORDERS hdr_b_type,
  17.            int pat, int hdr_pat)
  18.        : Window(coordinates, fName, h, s, b_type, hdr_b_type, res,
  19.            pat, hdr_pat)
  20.     {
  21.     item = new Item();
  22.     hot = HOT; pos = POS; start = START; itemSize = ITEMSIZE;
  23.     itemList = ITEMLIST; itemStrings = ITEMSTRINGS;
  24.     itemDistance = ITEMDISTANCE; statusPos = STATUSPOS;
  25.     statusType = STATUSTYPE; statusStrings = STATUSSTRINGS;
  26.     statusList = STATUSLIST;
  27.     calcConsts();
  28.     }
  29. ////////////////////////
  30. void ChoiceBox::calcConsts()
  31.     {
  32.     calcItemsNumber();
  33.     rect r = user_screen();
  34.     raw = (r.height() - itemDistance.Y)
  35.            / (screenYT(itemSize.Y) + itemDistance.Y);
  36.     if(raw == 0)
  37.         raw = r.height() / screenYT(itemSize.Y);
  38.  
  39.     column = (r.width() - itemDistance.X)
  40.            / (screenXL(itemSize.X) + itemDistance.X);
  41.  
  42.     if(column > count)      // if not enough items for filling the box
  43.     column = count;
  44.  
  45.     if((raw == 1 && screenYT(itemSize.Y) > r.height())
  46.         || (screenXL(itemSize.X) + 2 * itemDistance.X > r.width())
  47.     || (raw != 1 && screenYT(itemSize.Y) + 2 * itemDistance.Y > r.height()))
  48.     {
  49.     available = 0;
  50.     return;
  51.     }
  52.     available = 1;
  53.     }
  54. ////////////////////////////
  55. void ChoiceBox::hide()
  56.     {
  57.     if(once && *fileName != '\0')
  58.     item->hide(getItemCoord());
  59.     Window::hide();
  60.     }
  61. ///////////////////////////
  62. void ChoiceBox::moveTo(int number)
  63.     {
  64.     if(number == 0)
  65.     return;
  66.     item->hide(getItemCoord());
  67.     if(number < start || number > start + raw * column - 1)
  68.     {
  69.     start = pos = number;
  70.     show();
  71.     return;
  72.     }
  73.     pos = number;
  74.     item->show(getItemCoord());
  75.     showStatus(number, pattern);
  76.     }
  77. ////////////////////////////
  78. void ChoiceBox::endOfList()
  79.     {
  80.     if(pos == count)
  81.     {
  82.     pos = 1;
  83.     start = 1;
  84.     }
  85.     else
  86.     {
  87.     pos = count;
  88.     if(count <= raw * column)
  89.         start = 0;
  90.     else
  91.         start = count - raw * column + 1;
  92.     }
  93.     }
  94. //////////////////////////
  95. void ChoiceBox::home()
  96.     {
  97.     item->hide(getItemCoord());
  98.     pos = start;
  99.     moveTo(pos);
  100.     }
  101. ////////////////////////
  102. void ChoiceBox::end()
  103.     {
  104.     item->hide(getItemCoord());
  105.     if(column * raw - pos + start > count - pos)
  106.     pos = count;
  107.     else
  108.     pos = start + column * raw - 1;
  109.     moveTo(pos);
  110.     }
  111. ////////////////////////
  112. void ChoiceBox::pgUp()
  113.     {
  114.     item->hide(getItemCoord());
  115.     if(pos >= raw * column)
  116.     pos -= raw * column;
  117.     else
  118.     pos = 1;
  119.     moveTo(pos);
  120.     }
  121. ////////////////////////
  122. void ChoiceBox::pgDn()
  123.     {
  124.     item->hide(getItemCoord());
  125.     if(count >= pos + column * raw)
  126.     pos += column * raw;
  127.     else
  128.     pos = count;
  129.     moveTo(pos);
  130.     }
  131. ////////////////////////
  132. void ChoiceBox::left()
  133.     {
  134.     item->hide(getItemCoord());
  135.     if(pos > 1)
  136.     pos--;
  137.     else
  138.     pos = count;
  139.     moveTo(pos);
  140.     }
  141. ////////////////////////
  142. void ChoiceBox::right()
  143.     {
  144.     item->hide(getItemCoord());
  145.     if(count >= pos + 1)
  146.     pos++;
  147.     else
  148.     pos = 1;
  149.     moveTo(pos);
  150.     }
  151. ////////////////////////
  152. void ChoiceBox::up()
  153.     {
  154.     item->hide(getItemCoord());
  155.     if(pos > column)
  156.     pos -= column;
  157.     else
  158.     pos = count;
  159.     moveTo(pos);
  160.     }
  161. ////////////////////////
  162. void ChoiceBox::dn()
  163.     {
  164.     item->hide(getItemCoord());
  165.     if(count >= pos + column)
  166.     pos += column;
  167.     else
  168.     pos = 1;
  169.     moveTo(pos);
  170.     }
  171. ////////////////////////
  172. void ChoiceBox::toTop()
  173.     {
  174.     item->hide(getItemCoord());
  175.     pos = 1;
  176.     moveTo(pos);
  177.     }
  178. /////////////////////////
  179. void ChoiceBox::toBottom()
  180.     {
  181.     item->hide(getItemCoord());
  182.     pos = count;
  183.     moveTo(pos);
  184.     }
  185. /////////////////////////
  186. int ChoiceBox::mouseOn(event e)
  187.     {
  188.     rect r = user_screen();
  189.     loc wh = e.where();
  190.     int mouse_raw = (wh.Y - r.origin.Y
  191.              - itemDistance.Y)
  192.                / (screenYT(itemSize.Y) + itemDistance.Y);
  193.     int mouse_col = (wh.X - r.origin.X
  194.              - itemDistance.X)
  195.              / (screenXL(itemSize.X) + itemDistance.X);
  196.     int result;
  197.     result = mouse_raw * column + mouse_col + 1;
  198.     return (result > count || result < 0) ? 0 : result;
  199.     }
  200. /////////////////////////
  201. rect ChoiceBox::getItemCoord()
  202.     {
  203.     rect rec = user_screen();
  204.     int position = pos - start;
  205.     int r = position / column;           // first raw is 0
  206.     int c = position - r * column;       // first column is 0
  207.     int left = c * (screenXL(itemSize.X) + itemDistance.X)
  208.                   + itemDistance.X;
  209.     int right = left + screenXR(itemSize.X) + 2; // + itemDistance.X);
  210.     int top = r * (screenYT(itemSize.Y) + itemDistance.Y)
  211.                   + itemDistance.Y;
  212.     int bottom = top + screenYB(itemSize.Y) + 2; // + itemDistance.Y);
  213.     return rect(rec.origin.X + left, rec.origin.Y + top,
  214.         rec.origin.X + right, rec.origin.Y + bottom);
  215.     }
  216. //////////////////////////
  217. void ChoiceBox::show()
  218.     {
  219.     Window::show();
  220. //    Window::clrscr();
  221.     if(!available || (itemStrings == NULL && itemList == NULL))
  222.     return;
  223.     int p = pos;
  224.     for(int i = 1; i <= raw; i++)
  225.     {
  226.     for(int j = 1; j <= column; j++)
  227.         {
  228.         pos = start + (i - 1) * column + j - 1;
  229.         showItem();
  230.         if(pos == count)
  231.         break;
  232.         }
  233.     if(pos == count)
  234.         break;
  235.     }
  236.     pos = p;
  237.     moveTo(pos);
  238.     }
  239. ///////////////////////////
  240. void ChoiceBox::repose(rect new_coord)
  241.     {
  242.     Window::repose(new_coord);
  243.     calcConsts();
  244.     }
  245. ///////////////////////////
  246. void ChoiceBox::exe(int act)
  247.     {
  248.     e.what = act ? KEYEVENT : NOEVENT;
  249.  
  250.     switch(act)
  251.     {
  252.     case AC_LEFT:   e.key = EVENT_LEFT; break;
  253.     case AC_RIGHT:  e.key = EVENT_RIGHT; break;
  254.     case AC_UP:     e.key = EVENT_UP; break;
  255.     case AC_DOWN:   e.key = EVENT_DN; break;
  256.     case AC_PG_UP:  e.key = EVENT_PG_UP; break;
  257.     case AC_PG_DN:  e.key = EVENT_PG_DN; break;
  258.     case AC_CTRL_PG_UP: e.key = EVENT_CTRL_PG_UP; break;
  259.     case AC_CTRL_PG_DN: e.key = EVENT_CTRL_PG_DN; break;
  260.     case AC_CANCEL: e.key = (isRet(RET_REMOVE))
  261.         ? EVENT_ALT_F3 : EVENT_ESC;
  262.         break;
  263.     case AC_OK:     e.key = EVENT_F2; break;
  264.     }
  265.     int res = pos;    // reserv, used if we input ESC - like command
  266.     rect r = textRect(user_screen());
  267.     mouseHideCursor();
  268.     if(!act)
  269.     hilite();
  270.  
  271.     int on = 0;
  272.     mouseShowCursor();
  273.     while(1)
  274.     {
  275.     mouseShowCursor();
  276.     if(!act && !(e.what == MOUSEEVENT && !on))
  277.         get_event();
  278.     else
  279.         on = 1;
  280.     mouseHideCursor();
  281.     if(statusType)        // status line
  282.         showStatus(pos, pattern);
  283.  
  284.     char* ch = 0;        // hot keys
  285.     if(hot != NULL
  286.         && (ch = strchr(strlwr(hot), e.keypress())) && (e.key < 256 )
  287.         && e.keypress())
  288.         {
  289.         moveTo(ch - hot + 1);
  290.         e.what = KEYEVENT;
  291.         e.key = EVENT_RETURN;
  292.         }
  293.  
  294.     if(e.what == KEYEVENT)
  295.         switch(e.key)
  296.         {
  297.         case EVENT_F1: global_i[0] = action_type; return;
  298.         case EVENT_RIGHT: if(available) right();   break;
  299.         case EVENT_LEFT: if(available) left();    break;
  300.         case EVENT_UP: if(available) up(); break;
  301.         case EVENT_DN: if(available) dn(); break;
  302.         case EVENT_HOME:  if(available) home(); break;
  303.         case EVENT_PG_UP: if(available) pgUp(); break;
  304.         case EVENT_END:   if(available) end(); break;
  305.         case EVENT_PG_DN: if(available) pgDn(); break;
  306.         case EVENT_CTRL_PG_UP: if(available) toTop(); break;
  307.         case EVENT_CTRL_PG_DN: if(available) toBottom(); break;
  308.         case EVENT_ESC: if(available) moveTo(res); global_num = 0;
  309.             global_i[0] = AC_NULL; return;
  310.         case EVENT_F6:
  311.         case EVENT_F10:
  312.         case EVENT_TAB:
  313.         case EVENT_ALT_F3:
  314.         case EVENT_ALT_F4:
  315.         case EVENT_ALT_TAB:
  316.             unhilite(); global_num = pos;
  317.             global_i[0] = 0; return;
  318.         case EVENT_F2:
  319.         case EVENT_RETURN :  unhilite(); global_num = pos;
  320.             global_i[0] = action_type; return;
  321.         }
  322.     else
  323.         {
  324.         if(!mouse_in(e.where()))
  325.         {
  326.         unhilite();
  327.         global_num = 0; global_i[0] = AC_NULL;
  328.         return;
  329.         }   // outside of menu box
  330.         int new_pos;
  331.  
  332.         if((new_pos = start + mouseOn(e) - 1) && available)             // mouse pressed at the item
  333.         {
  334.         item->hide(getItemCoord());
  335.         unhilite();
  336.         e.what = KEYEVENT;
  337.         e.key = EVENT_RETURN;
  338.         global_num = new_pos;
  339.         moveTo(new_pos);
  340.         global_i[0] = action_type;
  341.         return;
  342.         }
  343.         }
  344.     if(act)    // leave menu and return to the object which calls it
  345.         {      // after single processing of "act" command
  346.         global_num = pos;
  347.         return;
  348.         }
  349.     }
  350.     }
  351. //////////////////////////
  352.  
  353.